﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RabbitMQ.Client;
using XYS.Core.Models;
using XYS.Core.Util.Helper;
using XYS.Service.Core.EventBus;
using XYS.Service.Core.EventBus.Abstractions;
using XYS.Service.Core.EventBus.EventBusRabbitMQ;

namespace XYS.Service.Core
{
    /// <summary>
    /// 添加 事件总线
    /// </summary>
    public static class EventBusExtension
    {

        private static List<Type> integrationEventHandlers = new();

        /// <summary>
        /// 添加 事件总线
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="logger"></param>
        /// <returns></returns>
        public static WebApplicationBuilder AddEventBus(this WebApplicationBuilder builder, ILogger logger)
        {
            var eventBugSetting = builder.Configuration.GetSection("EventBugSetting").Get<EventBugSetting>();
            if (eventBugSetting != null && eventBugSetting.Enable)
            {
                builder.Services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
                {
                    var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
                    var factory = new ConnectionFactory()
                    {
                        HostName = eventBugSetting.Host,
                        Port = eventBugSetting.Port,
                        DispatchConsumersAsync = true,
                        UserName = eventBugSetting.UserName,
                        Password = eventBugSetting.Password,
                        ClientProvidedName = $"{GlobalCoreSetting.ServiceName}-eventBus"
                    };
                    return new DefaultRabbitMQPersistentConnection(factory, logger, eventBugSetting.RetryCount);
                });

                builder.Services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
                {
                    string subscriptionClientName = $"event-sub-{GlobalCoreSetting.ServiceName}";
                    var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();

                    var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
                    var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();

                    return new EventBusRabbitMQ(sp, rabbitMQPersistentConnection, logger, eventBusSubcriptionsManager, subscriptionClientName, eventBugSetting.RetryCount);
                });

                builder.Services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();

                //获取所有 事件集成器
                integrationEventHandlers = AssemblyHelper.GetAssemblyTypes()
                    .Where(e => typeof(IIntegrationEventHandler).IsAssignableFrom(e) && e.IsClass)
                    .Where(x => x != null && !string.IsNullOrWhiteSpace(x.FullName))
                    .ToList();

                if (integrationEventHandlers.Any())
                {
                    integrationEventHandlers = integrationEventHandlers.Where(x => x.GetInterfaces().Any(n => n.Name.Contains(typeof(IIntegrationEventHandler<>).Name) && n.GenericTypeArguments.Any())).ToList();

                    foreach (var item in integrationEventHandlers)
                    {
                        //自动添加 集成器
                        builder.Services.AddTransient(item);
                    }
                }
            }

            return builder;
        }

        /// <summary>
        /// 使用 事件总线
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static WebApplication UseEventBus(this WebApplication app)
        {
            var eventBugSetting = app.Configuration.GetSection("EventBugSetting").Get<EventBugSetting>();
            if (eventBugSetting != null && eventBugSetting.Enable)
            {
                if (integrationEventHandlers.Any())
                {
                    var eventBus = app.Services.GetRequiredService<IEventBus>();

                    var eventBusType = eventBus.GetType();
                    var methodSubscribe = eventBusType.GetMethod("Subscribe");

                    foreach (var item in integrationEventHandlers)
                    {
                        var integrationEventHandler = item.GetInterfaces().Where(x => x.GenericTypeArguments.Any() && x.Name == typeof(IIntegrationEventHandler<>).Name).First();
                        var integrationEventType = integrationEventHandler.GenericTypeArguments.First();

                        //启用订阅事件
                        methodSubscribe.MakeGenericMethod(integrationEventType, item).Invoke(eventBus, Array.Empty<object>());
                        //eventBus.Subscribe<IntegrationEvent, IntegrationEventHandling>();
                    }
                }
            }
            return app;
        }

    }
}
